
/*
 * Copyright (C) 2009 Archie L. Cobbs. All rights reserved.
 *
 * $Id: CharacterField.java 377 2010-03-11 20:50:18Z archie.cobbs $
 */

package org.dellroad.sidekar;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.regex.Matcher;

import org.dellroad.stuff.string.ParseContext;

/**
 * Character field.
 *
 * @see org.dellroad.sidekar.annotation.SidekarField
 */
public final class CharacterField extends AtomicField<Character> {

    CharacterField(String name, Entity<?> entity) {
        super(name, entity, Character.class);
    }

    @Override
    public void visit(FieldSwitch fieldSwitch) {
        fieldSwitch.caseCharacterField(this);
    }

    @Override
    public void encode(DataOutputStream output, Character value) throws IOException {
        output.writeChar(value);
    }

    @Override
    public Character decode(DataInputStream input) throws IOException {
        return input.readChar();
    }

    @Override
    public String toString(Character value) {
        StringBuilder buf = new StringBuilder(4);
        buf.append('\'');
        char ch = value.charValue();
        switch (ch) {
        case '\\':
        case '\'':
            buf.append('\\');
            break;
        case '\n':
            buf.append('\\');
            ch = 'n';
            break;
        case '\r':
            buf.append('\\');
            ch = 'r';
            break;
        case '\f':
            buf.append('\\');
            ch = 'f';
            break;
        case '\t':
            buf.append('\\');
            ch = 't';
            break;
        default:
            break;
        }
        buf.append(ch);
        buf.append('\'');
        return buf.toString();
    }

    @Override
    public Character fromString(ParseContext ctx) {
        Matcher matcher = ctx.matchPrefix("'((\\\\('|\\\\|n|r|f|t))|([^'\\\\]))'");
        if (matcher.group(2) == null)
            return matcher.group(4).charAt(0);
        switch (matcher.group(3).charAt(0)) {
        case '\\':
            return '\\';
        case '\'':
            return '\'';
        case 'n':
            return '\n';
        case 'r':
            return '\r';
        case 'f':
            return '\f';
        case 't':
            return '\t';
        default:
            throw new RuntimeException("impossible case");
        }
    }
}

